/*+*********************************************************
Filename: 04_eth_04\src\top.v
Description:
  transfer mic data on ethernet.

Modification:
2024.03.14 creation by H.Zheng
2024.03.20 change udp payload (mic sample data) from big-endian to little-endian,
           16bit with 2 channel(same data).
2024.04.16 change ip&mac addr as parameter, change UART_FRE to 50k
**********************************************************-*/

module top(
	input                        clk,
	input                        rst_n,
	input                        uart_rx,
	output                       uart_tx,
    output wire [5:0] led, 
    output wire ety_phyrst,
    input netrmii_clk50m,
    input netrmii_rx_crs,
    output netrmii_mdc,
    output netrmii_txen,
    inout netrmii_mdio,
    output [1:0] netrmii_txd,
    input [1:0] netrmii_rxd,
    output wire mic_ws,
    output wire mic_ck,
    output wire mic_lr,
    input wire mic_data
);

	parameter DEST_MAC_ADDR = 48'hff_ff_ff_ff_ff_ff; 
	parameter SRC_MAC_ADDR = {8'h06, 8'h00, 8'haa, 8'hbb, 8'h0c, 8'hdd}; 
	parameter DEST_IP_ADDR = {8'd192,8'd168,8'd15,8'd15}; 
	parameter SRC_IP_ADDR = {8'd192,8'd168,8'd15,8'd14}; 
	parameter DEST_UDP_PORT = 16'd5678; 
	parameter SRC_UDP_PORT = 16'd1234;


//assign led = 6'b111001;


/**
 * clock section
 */
wire clk1m;
wire clk6m;
PLL_6M PLL6m(
    .clkout(clk6m),
    .clkoutd(clk1m),
    .clkin(clk)
);

  /**
   * ety section
   */
  wire [31:0] udp_data;
  wire udp_data_clk;


  ety#(.DEST_MAC_ADDR(DEST_MAC_ADDR),	.SRC_MAC_ADDR(SRC_MAC_ADDR), 
       .DEST_IP_ADDR(DEST_IP_ADDR), .SRC_IP_ADDR(SRC_IP_ADDR),
       .DEST_UDP_PORT(DEST_UDP_PORT), .SRC_UDP_PORT(SRC_UDP_PORT)) m_ety(
    .clk1m(clk1m), 
    .rst_n(rst_n),
    .ety_phyrst(ety_phyrst),
    .netrmii_clk50m(netrmii_clk50m),
    .netrmii_rx_crs(netrmii_rx_crs),
    .netrmii_mdc(netrmii_mdc),
    .netrmii_txen(netrmii_txen),
    .netrmii_mdio(netrmii_mdio),
    .netrmii_txd(netrmii_txd),
    .netrmii_rxd(netrmii_rxd),
    .data(udp_data),
    .data_clk(udp_data_clk)
  );


/**
 * uart section
 */

parameter                        CLK_FRE  = 27;//Mhz
//parameter                        UART_FRE = 115200;//hz
parameter                        UART_FRE = 500000;//hz
wire[7:0]                         tx_data;
wire                              tx_data_valid;
wire                             tx_data_ready;


uart_tx#
(
	.CLK_FRE(CLK_FRE),
	.BAUD_RATE(UART_FRE)
) uart_tx_inst
(
	.clk                        (clk                      ),
	.rst_n                      (rst_n                    ),
	.tx_data                    (tx_data                  ),
	.tx_data_valid              (tx_data_valid            ),
	.tx_data_ready              (tx_data_ready            ),
	.tx_pin                     (uart_tx                  )
);

/**
 * mic part
 */
assign mic_lr = 1'b0;

reg [7:0] mic_counter;

always @(posedge clk6m or negedge rst_n) begin
    if (!rst_n)
        mic_counter <= 8'd0;
    else
        mic_counter <= mic_counter + 1'd1;
end

wire clk_3072kHz_n = mic_counter[0];  //6/2
wire clk_48kHz_n   = mic_counter[6]; //3/64=6/128

assign mic_ck = clk_3072kHz_n;
assign mic_ws = clk_48kHz_n;


/**
 * receive mic data
 */
reg [63:0] shift_reg;

always @(posedge mic_ck) begin
    shift_reg <= {shift_reg[62:0], mic_data};	
end	
    
reg [63:0] data_reg;
always  @(negedge mic_ws) begin
    data_reg <= shift_reg;
end		

wire[23:0] data_l = data_reg[62:39];	
wire[23:0] data_r = data_reg[30:7];	    

//assume that it's signed data    
wire[22:0] l_amplitude = data_l[23] ? ((~data_l[22:0])+1'b1) : data_l[22:0];
wire loud_voice = (l_amplitude[22:16]>=7'h07) ? 1'b1 : 1'b0;    


//uart tx data and trigger signal
assign tx_data = data_l[23:16];
reg [1:0] mic_ws_edge;
always @(negedge clk) begin
    mic_ws_edge <= {mic_ws_edge[0], mic_ws};	
end
assign tx_data_valid = (~mic_ws_edge[1]) & mic_ws_edge[0]; //posedge of mic_ws trigger a uart tx


//udp-ety fifo write data
assign udp_data_clk = tx_data_valid;
//assign udp_data = {{8{data_l[23]}}, data_l};
//change data from big-indian to little-indian
//and 16bit width, repeat for 2 channel
assign udp_data = {data_l[15:8],data_l[23:16],data_l[15:8],data_l[23:16]};


/**
 * led
 */

//assign led = {~eth_tx_flag, 4'b0011, ~phy_rdy};
assign led = {5'b11111 , ~loud_voice};
//assign led = ~l_amplitude[22:17];

endmodule